#include "tchannel.h"

//#include <time.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

#ifdef __linux__
#define printf_s printf
#define sprintf_s sprintf
#include <stdexcept>
#endif

#include "dtypedef.h"
#include "business_def.h"
#include "pfunc.h"
#include "luadisp.h"
#include "Log.h"

TranChannel::TranChannel(int tid_)
{
	BusinessDef *ptr_BDef = BusinessDef::getInstance();
	if(!ptr_BDef->getTranInfoByID(tid_,tatts))
	{
		CLogger::createInstance()->Log(MsgWarn,
			"TranChannel(%d) is not map atts config! [%s %s %d]"
			, tid_, __FILE__, __FUNCTION__, __LINE__);
	}
	char buf[128]={0};
	sprintf(buf,"%s[%d]_read_tran",tatts.name.c_str(),tatts.id);
	ReadDatas = new QueueData<ChannelCmd>(std::string(buf));
	sprintf(buf,"%s[%d]_write_tran",tatts.name.c_str(),tatts.id);
	WriteDataS = new QueueData<ChannelToTransmit>(std::string(buf));
	ToGchannelDatas = QueueDataSingle<TransmitToGChannel>::getInstance();
	ToGchannelDatas->setQueueDesc("To_Gchannel_queue");
	//获取采集信道匹配的协议配置
	if(!ptr_BDef->getProtocolInfoByTID(tid_,protodefs))
	{
		CLogger::createInstance()->Log(MsgWarn,
			"TranChannel(%d) is not map protocol config! [%s %s %d]"
			, tid_, __FILE__, __FUNCTION__, __LINE__);
	}
	//
	if(!ptr_BDef->getProtocolTypeByTID(tid_,protoType))
	{
		CLogger::createInstance()->Log(MsgWarn,
			"TranChannel(%d) is not define protocol type! [%s %s %d]"
			, tid_, __FILE__, __FUNCTION__, __LINE__);
	}
	this->initLua();
}


TranChannel::~TranChannel(void)
{
	releaseLua();
};

int TranChannel::getBuffer(unsigned char * _buf)
{
	switch (protoType)
	{
	case 1:
		return getBufferTran(_buf);
	case 2:
		return getBufferDef(_buf);
	case 3:
		return getBufferDefList(_buf);
	default:
		return 0;
	}
};

int TranChannel::getHeartBeatBuffer(unsigned char * buf)
{
	if (NULL != buf) {
		int idx = 0;

		buf[idx++] = 0xF9;		//0-STX
								//信息长度
		buf[idx++] = 0xf0;		//1-Len_L
		buf[idx++] = 0xf0;		//2-Len_H
		//time
		unsigned int cur_time = static_cast<unsigned int>(time(NULL));
		buf[idx++] = static_cast<unsigned char>(cur_time & 0xff);
		buf[idx++] = static_cast<unsigned char>((cur_time >> 8) & 0xff);
		buf[idx++] = static_cast<unsigned char>((cur_time >> 16) & 0xff);
		buf[idx++] = static_cast<unsigned char>((cur_time >> 24) & 0xff);
		//comment len
		buf[1] = static_cast<unsigned char>(idx & 0xff);
		buf[2] = static_cast<unsigned char>((idx >> 8) & 0xff);

		unsigned char m_end = 0xFF;
		memcpy(buf + idx, &m_end, 1);
		idx++;
		return idx;
	}
	else {
		return 0;
	}
};

int TranChannel::AddFrame(const unsigned char *buf, int len)
{
	switch (protoType)
	{
	case 1:
		return AddFrameTran(buf,len);
	case 2:case 3:
		return AddFrameDef(buf,len);
	default:
		Print_WARN("AddFrame error for protoType isn't map\n");
		return 0;
	}
};

void TranChannel::add(ChannelToTransmit it)
{
	WriteDataS->add(it);
}

void TranChannel::initLua()
{
	if (1 == protoType)
	{
		//协议解析脚本
		luaScript = new luadisp();
		if (!luaScript->open(protodefs.luafile.c_str()))
		{
			CLogger::createInstance()->Log(MsgError,
				"open lua_script file %s  fail! [%s %s %d]", protodefs.luafile.c_str()
				, __FILE__, __FUNCTION__, __LINE__);
		}
	}
	else {
		luaScript = NULL;
	}
};

void TranChannel::releaseLua()
{
	if (NULL != luaScript)
	{
		luaScript->close();
		delete luaScript;
		luaScript = NULL;
	}
};

int TranChannel::getBufferDef(unsigned char * buf)
{
	ChannelToTransmit it;
	if(WriteDataS->pop(it))
	{
		try{
			int idx = 0;
			//unsigned char buf[512] = {0};

			buf[idx++] = 0xF7;		//0-STX
			//信息长度
			buf[idx++] = 0xf0;		//1-Len_L
			buf[idx++] = 0xf0;		//2-Len_H
			//时间
			//buf[idx++] = static_cast<unsigned char>(it.evtTimeS & 0xff);
			//buf[idx++] = static_cast<unsigned char>((it.evtTimeS >> 8) &0xff);
			//buf[idx++] = static_cast<unsigned char>((it.evtTimeS >> 16) &0xff);
			//buf[idx++] = static_cast<unsigned char>((it.evtTimeS >> 24) &0xff);
			//buf[idx++] = static_cast<unsigned char>(it.evtTimeMS & 0xFF);		//时间毫秒值

			//pid
			buf[idx++] = static_cast<unsigned char>(it.pID & 0xff);
			buf[idx++] = static_cast<unsigned char>((it.pID >> 8) & 0xff);
			buf[idx++] = static_cast<unsigned char>((it.pID >> 16) & 0xff);
			buf[idx++] = static_cast<unsigned char>((it.pID >> 24) & 0xff);
			//
			buf[idx++] = static_cast<unsigned char>(it.pType & 0xff);
			//val
			unsigned char*vavch = (unsigned char*)&(it.val);
			buf[idx++] = vavch[3];
			buf[idx++] = vavch[2];
			buf[idx++] = vavch[1];
			buf[idx++] = vavch[0];
			vavch = NULL;
			//taskid
			unsigned long tranTaskID = it.changeF ? it.taskID : 0;
			buf[idx++] = static_cast<unsigned char>(tranTaskID & 0xff);
			buf[idx++] = static_cast<unsigned char>((tranTaskID >> 8) & 0xff);
			buf[idx++] = static_cast<unsigned char>((tranTaskID >> 16) & 0xff);
			buf[idx++] = static_cast<unsigned char>((tranTaskID >> 24) & 0xff);
			//comment len
			buf[1] = static_cast<unsigned char>(idx & 0xff);
			buf[2] = static_cast<unsigned char>((idx >> 8) & 0xff);

			unsigned char m_end = 0xFF;
			memcpy(buf+idx,&m_end,1);
			idx++;

			if (it.changeF&&it.taskID>0) 
			{
				CLogger::createInstance()->Log(MsgInfo,
					"TaskID[%lu] and up_node[4] getBufferDef, time(%s),pID(%d),pType(%d),val(%.3f)"
					, it.taskID, pyfree::getCurrentTime().c_str()
					, it.pID, static_cast<int>(it.pType), it.val);
			}
			// printf("send len(%d):\n", idx);
			// for (int i = 0; i < idx; i++)
			// {
			// 	printf("%02X", buf[i]);
			// }
			// printf("\n");
			return idx;
		}
		catch (const std::exception& e)
		{
			CLogger::createInstance()->Log(MsgError,
				"write item info to socket failed! have error[%s]. [%s %s %d]"
				, e.what()
				, __FILE__, __FUNCTION__, __LINE__);
		}
		catch (...) {
			//printf_s("write item info to socket failed! have error. \r\n");
			CLogger::createInstance()->Log(MsgFatal,
				"write item info to socket failed! have error. [%s %s %d]"
				, __FILE__, __FUNCTION__, __LINE__);
		}
	}
	return -1;
};

int TranChannel::getBufferDefList(unsigned char * buf)
{
	std::queue<ChannelToTransmit> its;
	if (WriteDataS->getList(its,10))
	{
		try
		{
			int idx = 0;
			//unsigned char buf[512] = {0};

			buf[idx++] = 0xF8;		//0-STX
									//信息长度
			buf[idx++] = 0xf0;		//1-Len_L
			buf[idx++] = 0xf0;		//2-Len_H
			//
			buf[idx++] = 0x00;		//size_L
			buf[idx++] = 0x00;		//size_H
			int sizeW = 0;
			while (!its.empty())
			{
				ChannelToTransmit it = its.front();
				//pid
				buf[idx++] = static_cast<unsigned char>(it.pID & 0xff);
				buf[idx++] = static_cast<unsigned char>((it.pID >> 8) & 0xff);
				buf[idx++] = static_cast<unsigned char>((it.pID >> 16) & 0xff);
				buf[idx++] = static_cast<unsigned char>((it.pID >> 24) & 0xff);
				//
				buf[idx++] = static_cast<unsigned char>(it.pType & 0xff);
				//val
				unsigned char*vavch = (unsigned char*)&(it.val);
				buf[idx++] = vavch[3];
				buf[idx++] = vavch[2];
				buf[idx++] = vavch[1];
				buf[idx++] = vavch[0];
				vavch = NULL;
				//taskid
				unsigned long tranTaskID = it.changeF ? it.taskID : 0;
				buf[idx++] = static_cast<unsigned char>(tranTaskID & 0xff);
				buf[idx++] = static_cast<unsigned char>((tranTaskID >> 8) & 0xff);
				buf[idx++] = static_cast<unsigned char>((tranTaskID >> 16) & 0xff);
				buf[idx++] = static_cast<unsigned char>((tranTaskID >> 24) & 0xff);
				sizeW += 1;//实际写入长度
				//
				if (it.changeF&&it.taskID > 0) 
				{
					CLogger::createInstance()->Log(MsgInfo,
						"TaskID[%lu] and up_node[4] getBufferDefList, time(%s),pID(%d),pType(%d),val(%.3f)"
						, it.taskID, pyfree::getCurrentTime().c_str()
						, it.pID, static_cast<int>(it.pType), it.val);
				}
				//
				its.pop();
			}
			//comment len
			buf[1] = static_cast<unsigned char>(idx & 0xff);
			buf[2] = static_cast<unsigned char>((idx >> 8) & 0xff);
			//ponit size
			buf[3] = static_cast<unsigned char>(sizeW & 0xff);
			buf[4] = static_cast<unsigned char>((sizeW >> 8) & 0xff);
			//
			unsigned char m_end = 0xFF;
			memcpy(buf + idx, &m_end, 1);
			idx++;
			
			// printf(".....................%d.........................\n",idx);
			//
			return idx;
		}
		catch (const std::exception& e)
		{
			CLogger::createInstance()->Log(MsgError,
				"write items info to socket failed! have error %s. [%s %s %d]"
				,e.what()
				, __FILE__, __FUNCTION__, __LINE__);
		}
	}
	return -1;
};

int TranChannel::AddFrameDef(const unsigned char *pBuf, int len)
{
	try {
		unsigned char type = pBuf[0];
		int idx = 1;
		switch (type)
		{
		case 0XF5://查询
		{
			int rlen = pBuf[idx++];
			rlen += (pBuf[idx++] << 8);
			if ((rlen + 1) != len) 
			{
				break;
			}
			//pid
			int pID = 0;
			pID += pBuf[idx++];
			pID += (pBuf[idx++] << 8);
			pID += (pBuf[idx++] << 16);
			pID += (pBuf[idx++] << 24);
			//type
			pyfree::PType pType = (pyfree::PType)pBuf[idx++];
			//val
			float Value = float(0.0);
			unsigned char* fval = (unsigned char*)&Value;
			fval[3] = pBuf[idx++];
			fval[2] = pBuf[idx++];
			fval[1] = pBuf[idx++];
			fval[0] = pBuf[idx++];
			fval = NULL;
			//task id
			unsigned long taskID = 0;
			taskID += pBuf[idx++];
			taskID += (pBuf[idx++] << 8);
			taskID += (pBuf[idx++] << 16);
			taskID += (pBuf[idx++] << 24);
			//end
			unsigned char endflag = pBuf[idx++];
			if (0XFF != endflag)
			{
				Print_WARN("error end for frame data in AddFrameDef\r\n");
			}
			if (pyfree::OnYX == pType) 
			{
				Value = Value > 0 ? float(1.0) : float(0.0);
			}
			ToGchannelDatas->add(TransmitToGChannel(pyfree::OnGet, pID, pType, Value, taskID));
			
			//printf_s("read data 0XF5:pID[%d],pType[%d],val[%.3f],endflag[%02X]\n"
			//	,  pID, pType, Value, endflag);
			//test
			//m_WDData->addWDS(WDS(pType, pID,1.0));

		}
		break;
		case 0XF6://设值
		{
			int rlen = pBuf[idx++];
			rlen += (pBuf[idx++] << 8);
			if ((rlen + 1) != len) 
			{
				break;
			}
			//pid
			int pID = 0;
			pID += pBuf[idx++];
			pID += (pBuf[idx++] << 8);
			pID += (pBuf[idx++] << 16);
			pID += (pBuf[idx++] << 24);
			//type
			pyfree::PType pType = (pyfree::PType)pBuf[idx++];
			//val
			float Value = float(0.0);
			unsigned char* fval = (unsigned char*)&Value;
			fval[3] = pBuf[idx++];
			fval[2] = pBuf[idx++];
			fval[1] = pBuf[idx++];
			fval[0] = pBuf[idx++];
			fval = NULL;
			//task id
			unsigned long taskID = 0;
			taskID += pBuf[idx++];
			taskID += (pBuf[idx++] << 8);
			taskID += (pBuf[idx++] << 16);
			taskID += (pBuf[idx++] << 24);
			unsigned char endflag = pBuf[idx++];
			if (0XFF != endflag)
			{
				Print_WARN("error end for frame data in AddFrameDef\r\n");
			}
			if (pyfree::OnYX == pType) 
			{
				Value = Value > 0 ? float(1.0) : float(0.0);
			}
			ToGchannelDatas->add(TransmitToGChannel(pyfree::OnSet, pID, pType, Value, taskID));
			
			//Print_NOTICE("read data 0XF6:pID[%d],pType[%d],val[%.3f],endflag[%02X]\n"
			//	, pID, pType, Value, endflag);
		}
		break;
		default:
		{
			char warBuf[128] = { 0 };
			sprintf(warBuf,"MonitorData::AddFrameDef For Unkown Type(%02X)", type);
			#ifdef WIN32
			throw std::exception(warBuf);
			#else
			throw std::domain_error(warBuf);
			#endif
		}
		break;
		}
		return 1;
	}
	catch (const std::exception& e)
	{
		CLogger::createInstance()->Log(MsgError,
			"AddFrameDef(%s,%d) func error[%s]. [%s %s %d]"
			, pBuf, len
			, e.what()
			, __FILE__, __FUNCTION__, __LINE__);
	}
	catch (...)
	{
		CLogger::createInstance()->Log(MsgFatal,
			"AddFrameDef(%s,%d) func error. [%s %s %d]"
			, pBuf, len
			, __FILE__, __FUNCTION__, __LINE__);
	}
	return -1;
};

int TranChannel::getBufferTran(unsigned char * buf)
{
	ChannelToTransmit it;
	if (WriteDataS->pop(it))
	{
		try {
			//you code for item data to cmd buf
			std::string _cmd = "";
			int checktype = 0;
			std::string _errormsg = "";
			memset(buf, 0, 256);
			int len = 0;
			//生成16进制字符串命令
			//in this, the allYXVal is taskid to tran the server
			if (luaScript->getDownControl(pyfree::OnTran, it.pType, it.pID
				, static_cast<int>(it.val), _cmd, checktype, _errormsg,it.taskID) 
				&& !_cmd.empty())
			{
				if (it.changeF&&it.taskID>0) 
				{
					CLogger::createInstance()->Log(MsgInfo,
						"TaskID[%lu] and up_node[4] getBufferTran, time(%s),pID(%d),pType(%d),val(%.3f)"
						", CMD(%s),checktype(%d)"
						, it.taskID, pyfree::getCurrentTime().c_str()
						, it.pID, static_cast<int>(it.pType), it.val
						, _cmd.c_str(), checktype);
				}
				switch (checktype)
				{
				case 1:
				{
					//转ACSII字符串
					len = pyfree::string2bytes(_cmd.c_str(), buf, static_cast<int>(_cmd.length()));
					unsigned int crc = pyfree::crc16(buf, len);
					sprintf((char*)buf, "%s%02X%02X", _cmd.c_str(), (crc & 0XFF), ((crc >> 8) & 0XFF));
					_cmd = std::string((char*)buf);
					len = static_cast<int>(_cmd.length());
				}
				break;
				case 2:
				{
					len = pyfree::string2bytes(_cmd.c_str(), buf, static_cast<int>(_cmd.length()));
					//for (int j = 0; j < len; j++) {
					//	printf("%02X", buf[j]);
					//}
					//printf("\n");
					_cmd = std::string((char*)buf, len);
				}
				break;
				default:
					break;
				}
				return len;

			}
			else
			{
				char bufc[512] = { 0 };
				sprintf(bufc, "getDownControl Error:exeType(%d),pID(%d),pType(%d),val(%.3f),errormsg(%s)"
					, static_cast<int>(pyfree::OnTran), it.pID, static_cast<int>(it.pType), it.val, _errormsg.c_str());
				#ifdef WIN32
				throw std::exception(bufc);
				#else
				throw std::logic_error(bufc);
				#endif
			}
		}
		catch (const std::exception& e)
		{
			CLogger::createInstance()->Log(MsgError,
				"getBufferTran for data to cmd error[%s]. [%s %s %d]"
				, e.what()
				, __FILE__, __FUNCTION__, __LINE__);
		}
		catch (...)
		{
			CLogger::createInstance()->Log(MsgFatal,
				"getBufferTran for data to cmd error. [%s %s %d]"
				, __FILE__, __FUNCTION__, __LINE__);
		}
	}
	return -1;
};

int TranChannel::AddFrameTran(const unsigned char *buf, int len)
{
	if (1 == protoType&&NULL != luaScript)
	{
		try {
			std::string recs = "";
			std::string _errormsg = "";
			char _buf[256] = { 0 };
			//转16进制字符串
			// int rlen = pyfree::bytes2string(buf, _buf, len);
			std::string atres = std::string((char*)_buf);
			if (luaScript->getReciveIDVAL(atres.c_str(), recs, _errormsg))
			{
				std::vector<std::string> _maps;
				if (pyfree::string_divide(_maps, recs, ";"))
				{
					int pID = 0;
					float Value = 0.0;
#ifdef WIN32
					pyfree::PType pType = pyfree::PType::PTDef;
					pyfree::ExeType exeType = pyfree::ExeType::ExeTDef;
#else
					pyfree::PType pType = pyfree::PTDef;
					pyfree::ExeType exeType = pyfree::ExeTDef;
#endif // WIN32
					unsigned long taskID = 0;
					for (size_t i = 0,mSize = _maps.size(); i < mSize; ++i)
					{
						std::vector<std::string> _map;
						if (pyfree::string_divide(_map, _maps[i], ",") && 5 == _map.size())
						{
							pID = atoi(_map[0].c_str());
							Value = static_cast<float>(atoi(_map[1].c_str()));
							pType = (pyfree::PType)atoi(_map[2].c_str());
							exeType = (pyfree::ExeType)atoi(_map[3].c_str());
							taskID = static_cast<unsigned long>(atol(_map[4].c_str()));
							//printf("id-val:%d,%.2f\n",_id,_val);
							ToGchannelDatas->add(TransmitToGChannel(exeType, pID, pType, Value, taskID));
						}
					}
				}
			}
			else {
				#ifdef WIN32
				throw std::exception(_errormsg.c_str());
				#else
				throw std::logic_error(_errormsg.c_str());
				#endif
			}
			return 1;
		}
		catch (const std::exception& e)
		{
			CLogger::createInstance()->Log(MsgError,
				"AddFrameTran(%s,%d) func error[%s]. [%s %s %d]"
				, buf, len
				, e.what()
				, __FILE__, __FUNCTION__, __LINE__);
		}
		catch (...) {
			CLogger::createInstance()->Log(MsgFatal,
				"AddFrameTran(%s,%d) func error. [%s %s %d]"
				, buf, len
				, __FILE__, __FUNCTION__, __LINE__);
		}
	}
	return -1;
}
